import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import '../../../providers/product_provider.dart';
import '../../../providers/device_provider.dart';
import '../../../repositories/device_repository.dart';
import 'dart:async';

class ChartDataPoint {
  final DateTime timestamp;
  final double value;
  
  ChartDataPoint({
    required this.timestamp,
    required this.value,
  });
}

class ChartSeries {
  final String name;
  final Color color;
  final List<ChartDataPoint> data;
  final RxBool isVisible;
  
  ChartSeries({
    required this.name,
    required this.color,
    required List<ChartDataPoint> dataPoints,
    bool isVisible = true,
  }) : data = dataPoints,
       isVisible = isVisible.obs;
}

class PropertyDefinition {
  final String identifier;
  final String name;
  final String dataType;
  final int accessMode;
  final double? min;
  final double? max;
  final String? unit;
  final String desc;
  
  PropertyDefinition({
    required this.identifier,
    required this.name,
    required this.dataType,
    required this.accessMode,
    this.min,
    this.max,
    this.unit,
    required this.desc,
  });
  
  factory PropertyDefinition.fromJson(Map<String, dynamic> json) {
    print('解析属性定义：$json');
    
    // 解析identifier，确保非空
    String identifier = '';
    if (json.containsKey('identifier')) {
      identifier = json['identifier']?.toString() ?? '';
    }
    
    // 解析名称，确保非空
    String name = '';
    if (json.containsKey('name')) {
      name = json['name']?.toString() ?? '';
    }
    
    // 如果name为空但有identifier，使用identifier作为name
    if (name.isEmpty && identifier.isNotEmpty) {
      name = identifier;
    }
    
    // 解析数据类型，默认为string
    String dataType = 'string';
    if (json.containsKey('dataType')) {
      dataType = json['dataType']?.toString() ?? 'string';
    }
    
    // 解析访问模式，默认为只读
    int accessMode = 1;
    if (json.containsKey('accessMode')) {
      if (json['accessMode'] == null) {
        accessMode = 1;
      } else if (json['accessMode'] is int) {
        accessMode = json['accessMode'];
      } else if (json['accessMode'] is String) {
        accessMode = int.tryParse(json['accessMode']) ?? 1;
      } else {
        accessMode = 1;
      }
    }
    
    // 解析最小值，如果是数值类型
    double? min;
    if (json.containsKey('min') && json['min'] != null) {
      if (json['min'] is num) {
        min = (json['min'] as num).toDouble();
      } else {
        min = double.tryParse(json['min'].toString());
      }
    }
    
    // 解析最大值，如果是数值类型
    double? max;
    if (json.containsKey('max') && json['max'] != null) {
      if (json['max'] is num) {
        max = (json['max'] as num).toDouble();
      } else {
        max = double.tryParse(json['max'].toString());
      }
    }
    
    // 解析单位
    String? unit;
    if (json.containsKey('unit') && json['unit'] != null) {
      unit = json['unit'].toString();
    }
    
    // 解析描述
    String desc = '';
    if (json.containsKey('desc')) {
      desc = json['desc']?.toString() ?? '';
    }
    
    return PropertyDefinition(
      identifier: identifier,
      name: name,
      dataType: dataType,
      accessMode: accessMode,
      min: min,
      max: max,
      unit: unit,
      desc: desc,
    );
  }
  
  bool get isReadable => accessMode == 1 || accessMode == 2;
  bool get isWritable => accessMode == 2;
  
  // 只有数值类型的属性才能画图表
  bool get canChart { 
    if (!isReadable) return false;
    
    // 数值类型属性可以画图表
    return dataType == 'int' || dataType == 'float' || dataType == 'double';
  }
}

class DeviceDataController extends GetxController {
  final int deviceId;
  final String deviceName;
  final ProductProvider productProvider = ProductProvider();
  final DeviceProvider deviceProvider = DeviceProvider();
  final DeviceRepository deviceRepository = Get.find<DeviceRepository>();
  
  DeviceDataController({required this.deviceId, required this.deviceName});
  
  final isLoading = true.obs;
  final errorMessage = RxnString();
  final timeRange = 'latest'.obs;
  final showCombinedChart = true.obs;
  final chartData = <String, List<ChartDataPoint>>{}.obs;
  final combinedChartData = <ChartSeries>[].obs;
  final deviceModel = Rxn<Map<String, dynamic>>();
  final deviceSn = RxString('');
  
  // 添加缺失的属性
  final legendsExpanded = true.obs;  // 控制图例展开/收起状态，默认展开
  List<ChartSeries> get chartSeries => combinedChartData;  // 图表数据的getter
  
  // 添加缺失的方法
  void toggleLegendsExpansion() {
    legendsExpanded.value = !legendsExpanded.value;
  }
  
  final isRefreshing = false.obs;
  
  // 物模型属性定义
  final properties = <PropertyDefinition>[].obs;
  
  // 物模型JSON
  final modelJson = "".obs;

  // 添加缓存
  static final Map<int, String> _deviceSnCache = {};
  static final Map<int, String> _modelJsonCache = {};
  static final Map<String, Map<String, dynamic>> _historyDataCache = {};
  
  final availableColors = [
    Colors.blue,
    Colors.red,
    Colors.green,
    Colors.orange,
    Colors.purple,
    Colors.teal,
    Colors.brown,
    Colors.pink,
    Colors.cyan,
    Colors.amber,
    Colors.indigo,
    Colors.lime,
    Colors.lightBlue,
    Colors.deepOrange,
    Colors.deepPurple,
    Colors.lightGreen,
    Color(0xFF7986CB), // 靛蓝色
    Color(0xFFFFA726), // 琥珀色
    Color(0xFF4DB6AC), // 浅绿松石色
    Color(0xFFFFD54F), // 琥珀色淡
    Color(0xFF9575CD), // 深紫色
    Color(0xFF8A65), // 深橙色
    Color(0xFF4FC3F7), // 浅蓝色
    Color(0xFF81C784), // 浅绿色
    Color(0xFFBA68C8), // 中紫色
    Color(0xFFA1887F), // 棕色
    Color(0xFF90A4AE), // 蓝灰色
    Color(0xFFFFB74D), // 橙色
  ];

  // 表格相关状态
  final tableCurrentPage = 1.obs;
  final tablePageSize = 20; // 将每页显示条数从50改为20条
  final RxInt totalTimestamps = 0.obs;
  final RxList<DateTime> currentTimestamps = <DateTime>[].obs; // 存储所有排序后的时间戳
  final RxList<DateTime> paginatedTimestamps = <DateTime>[].obs; // 当前页的时间戳
  final showAllData = false.obs; // 默认使用分页显示数据
  int get totalTablePages => totalTimestamps.value == 0 ? 1 : (totalTimestamps.value / tablePageSize).ceil();

  // 添加一个变量保存服务器返回的总记录数
  final RxInt serverTotalCount = 0.obs;

  @override
  void onInit() {
    super.onInit();
    // 初始化时设置appbar标题
    updateAppBarTitle();
    _initDeviceData();
  }
  
  // 更新AppBar标题
  void updateAppBarTitle() {
    if (deviceName.isNotEmpty) {
      // 直接使用Get.toNamed路由方式时，通过路由参数来控制标题
      // 不需要使用AppBarController，使用UI层自行处理标题
      // 这里留空即可，或在UI中直接设置标题
      print('设备名称: $deviceName');
    }
  }
  
  // 优化初始化流程
  Future<void> _initDeviceData() async {
    try {
      isLoading.value = true;
      errorMessage.value = null;
      
      // 检查设备ID是否有效
      if (deviceId <= 0) {
        errorMessage.value = '设备ID无效，请返回设备列表重新选择';
        isLoading.value = false;
        return;
      }
      
      // 设置超时和错误恢复机制
      const timeout = Duration(seconds: 8); // 设置8秒超时
      
      // 1. 获取设备序列号 (使用缓存)
      if (_deviceSnCache.containsKey(deviceId)) {
        deviceSn.value = _deviceSnCache[deviceId]!;
        print('使用缓存的设备序列号: ${deviceSn.value}');
      } else {
        // 添加超时保护
        await _fetchDeviceSn().timeout(timeout, onTimeout: () {
          print('获取设备序列号超时');
          throw TimeoutException('获取设备序列号超时，请检查网络连接');
        });
      }
      
      // 如果获取不到序列号，提前显示UI提示用户
      if (deviceSn.isEmpty) {
        errorMessage.value = '无法获取设备序列号，请稍后再试';
        isLoading.value = false;
        return;
      }
      
      // 2. 尝试获取物模型（有超时保护）
      bool modelSuccess = false;
      try {
        await _fetchThingModel().timeout(timeout, onTimeout: () {
          print('获取物模型超时');
          return;
        });
        modelSuccess = properties.isNotEmpty;
      } catch (e) {
        print('获取物模型失败: $e');
        modelSuccess = properties.isNotEmpty;
      }
      
      // 3. 如果有物模型，获取历史数据
      if (modelSuccess) {
        try {
          await _fetchHistoryData().timeout(timeout, onTimeout: () {
            print('获取历史数据超时');
            // 不抛出异常，允许UI显示空状态
            return;
          });
        } catch (e) {
          print('获取历史数据失败: $e');
          // 不阻止UI显示，可能只是没有历史数据
        }
      }
    } on TimeoutException catch (e) {
      print('操作超时: $e');
      errorMessage.value = '加载超时: 网络连接较慢，请稍后再试';
    } catch (e) {
      print('初始化设备数据失败: $e');
      errorMessage.value = '加载设备数据失败: $e';
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> _fetchDeviceSn() async {
    try {
      // 有些设备可能有旧数据，直接从URL参数获取
      if (deviceName.isNotEmpty && deviceId > 0) {
        print('使用已知设备ID直接处理: $deviceId');
      }
      
      final deviceDetail = await deviceProvider.getDeviceDetail(deviceId);
      if (deviceDetail.isSuccess && deviceDetail.data != null) {
        deviceSn.value = deviceDetail.data!.deviceSn;
        // 缓存设备序列号
        _deviceSnCache[deviceId] = deviceSn.value;
        print('获取设备序列号成功: ${deviceSn.value}');
      } else {
        print('设备信息请求失败: ${deviceDetail.msg}');
        errorMessage.value = '获取设备信息失败：${deviceDetail.msg}';
      }
    } catch (e) {
      print('获取设备序列号异常: $e');
      errorMessage.value = '获取设备序列号失败：$e';
      rethrow; // 重新抛出异常让上层处理
    }
  }
  
  Future<void> _fetchThingModel() async {
    if (deviceSn.isEmpty) return;
    
    try {
      // 检查缓存
      if (_modelJsonCache.containsKey(deviceId)) {
        modelJson.value = _modelJsonCache[deviceId]!;
        print('使用缓存的物模型');
        getPropertiesFromJson();
        return;
      }
      
      // 使用产品ID获取物模型JSON数据
      int? productId;
      try {
        // 获取设备详情以获取产品ID
        final deviceDetailResponse = await deviceProvider.getDeviceDetail(deviceId);
        if (!deviceDetailResponse.isSuccess || deviceDetailResponse.data == null) {
          throw Exception('获取设备详情失败: ${deviceDetailResponse.msg}');
        }
        
        productId = deviceDetailResponse.data!.productId;
        print('设备 $deviceId 关联的产品ID: $productId');
      } catch (e) {
        print('获取产品ID失败: $e');
        throw Exception('无法获取产品信息');
      }

      final response = await productProvider.getProductThingModel(productId);
      modelJson.value = response.modelJson;
      
      // 缓存物模型
      _modelJsonCache[deviceId] = modelJson.value;
      
      // 解析物模型
      getPropertiesFromJson();
    } catch (e) {
      print('获取设备物模型失败: $e');
    }
  }
  
  Future<void> _fetchHistoryData() async {
    if (deviceSn.isEmpty) return;
    
    try {
      // 检查缓存
      final cacheKey = '${deviceSn.value}_${timeRange.value}';
      if (_historyDataCache.containsKey(cacheKey)) {
        final cachedData = _historyDataCache[cacheKey];
        if (cachedData != null) {
          print('使用缓存的历史数据');
          _processResponseData(cachedData);
          return;
        }
      }
      
      // 默认请求参数 - 最新数据模式
      final Map<String, dynamic> queryParams = {
        'deviceSn': deviceSn.value,
        'pageSize': 5000, // 再次增加获取数据量，确保能获取所有数据
        'pageNum': 1,
      };
      
      // 根据时间范围设置时间参数
      if (timeRange.value != 'latest') {
        // 计算时间范围
        final DateTime now = DateTime.now();
        int startTimestamp;
        final int endTimestamp = now.millisecondsSinceEpoch;
        
        switch (timeRange.value) {
          case '24h':
            // 24小时前的时间戳
            startTimestamp = now.subtract(const Duration(hours: 24)).millisecondsSinceEpoch;
            print('选择时间范围: 24小时，开始时间: $startTimestamp');
            break;
          case '7d':
            // 7天前的时间戳
            startTimestamp = now.subtract(const Duration(days: 7)).millisecondsSinceEpoch;
            print('选择时间范围: 7天，开始时间: $startTimestamp');
            break;
          case '30d':
            // 30天前的时间戳
            startTimestamp = now.subtract(const Duration(days: 30)).millisecondsSinceEpoch;
            print('选择时间范围: 30天，开始时间: $startTimestamp');
            break;
          default:
            // 默认24小时
            startTimestamp = now.subtract(const Duration(hours: 24)).millisecondsSinceEpoch;
            print('默认时间范围: 24小时，开始时间: $startTimestamp');
            break;
        }
        
        // 将时间戳转换为字符串并添加到查询参数
        queryParams['startTime'] = startTimestamp.toString();
        queryParams['endTime'] = endTimestamp.toString();
      } else {
        print('使用最新数据模式，不指定时间范围');
      }
      
      // 获取历史数据
      final response = await deviceRepository.getDevicePropertiesHistory(
        deviceSn: deviceSn.value,
        pageSize: queryParams['pageSize'],
        pageNum: queryParams['pageNum'],
        startTime: queryParams['startTime'],
        endTime: queryParams['endTime'],
      );
      
      // 缓存响应数据
      if (response is Map<String, dynamic>) {
        _historyDataCache['${deviceSn.value}_${timeRange.value}'] = response;
      }
      
      // 处理响应数据
      _processResponseData(response);
    } catch (e) {
      print('获取历史数据失败: $e');
      errorMessage.value = '获取历史数据失败：$e';
      // 不抛出异常，让UI显示空状态
    }
  }
  
  void _processResponseData(dynamic response) {
    // 等待物模型解析完成
    if (properties.isEmpty) {
      print('物模型未就绪，无法处理历史数据');
      chartData.value = {};
      combinedChartData.value = [];
      _updateTablePagination(); // 更新表格分页（即使没有数据）
      return;
    }
    
    try {
      // 获取可图表化的属性列表
      final chartableProps = properties.where((p) => p.canChart).toList();
      if (chartableProps.isEmpty) {
        print('没有可图表化的属性');
        chartData.value = {};
        combinedChartData.value = [];
        _updateTablePagination();
        return;
      }

      // 初始化数据映射
      final Map<String, List<ChartDataPoint>> data = {};
      
      // 为每个可图表化的属性创建空列表
      for (var prop in chartableProps) {
        final key = '${prop.name}${prop.unit != null ? "(${prop.unit})" : ""}';
        data[key] = [];
      }
      
      bool hasValidData = false;
      
      // 检查response是否为有效的Map
      if (response != null && response is Map<String, dynamic>) {
        // 保存服务器返回的总记录数
        if (response.containsKey('total') && response['total'] is int) {
          serverTotalCount.value = response['total'];
          print('服务器返回的总记录数: ${serverTotalCount.value}');
        }
        
        // 检查是否包含list字段
        if (response.containsKey('list')) {
          final historyList = response['list'];
          
          // 检查list是否为有效的List
          if (historyList is List && historyList.isNotEmpty) {
            print('成功获取到 ${historyList.length} 条历史数据');
            // 处理历史数据
            _processHistoryData(historyList, chartableProps, data);
            
            // 检查是否有任何数据点被成功解析
            int totalDataPoints = 0;
            data.forEach((key, points) {
              totalDataPoints += points.length;
            });
            
            if (totalDataPoints > 0) {
              print('成功解析 $totalDataPoints 个数据点');
              hasValidData = true;
            } else {
              print('没有成功解析任何数据点');
            }
          }
        }
      }
      
      // 过滤掉空数据系列
      data.removeWhere((key, points) => points.isEmpty);
      
      if (hasValidData && data.isNotEmpty) {
        // 更新图表数据
        chartData.value = data;
        
        // 生成合并图表数据
        _generateCombinedChartData();
        
        // 清除错误消息
        errorMessage.value = null;
      } else {
        print('响应中没有有效的数据点');
        chartData.value = {};
        combinedChartData.value = [];
      }
      
      // 总是更新表格分页信息
      _updateTablePagination();
    } catch (e) {
      print('处理响应数据失败: $e');
      chartData.value = {};
      combinedChartData.value = [];
      _updateTablePagination();
    }
  }
  
  void getPropertiesFromJson() {
    if (modelJson.isEmpty) {
      print('物模型JSON为空，无法解析属性');
      properties.clear();
      return;
    }
    
    try {
      final model = json.decode(modelJson.value);
      List<PropertyDefinition> props = [];
      
      // 处理标准属性
      if (model is Map && model.containsKey('properties')) {
        if (model['properties'] is List) {
          final propsList = model['properties'] as List;
          for (var prop in propsList) {
            if (prop is Map) {
              try {
                props.add(PropertyDefinition.fromJson(prop as Map<String, dynamic>));
              } catch (e) {
                print('解析属性时出错: $e，属性数据: $prop');
              }
            }
          }
        }
      }
      
      // 处理自定义属性或嵌套属性 - 确保能解析所有波浪参数
      if (model is Map && model.containsKey('waveParams') && model['waveParams'] is List) {
        final waveParams = model['waveParams'] as List;
        for (var param in waveParams) {
          if (param is Map) {
            try {
              props.add(PropertyDefinition.fromJson(param as Map<String, dynamic>));
            } catch (e) {
              print('解析波浪参数时出错: $e，参数数据: $param');
            }
          }
        }
      }
      
      // 如果JSON中没有标准属性，但有数据对象，尝试从最新数据中提取属性
      if (props.isEmpty && model is Map && model.containsKey('data')) {
        final data = model['data'];
        if (data is Map) {
          data.forEach((key, value) {
            // 跳过非数值类型属性
            if (value is num || (value is String && double.tryParse(value) != null)) {
              props.add(PropertyDefinition(
                identifier: key,
                name: _getPropertyDisplayName(key),
                dataType: value is int ? 'int' : 'float',
                accessMode: 1, // 只读
                desc: '',
              ));
            }
          });
        }
      }

      // 确保至少包含设备上报的所有属性
      final latestData = combinedChartData.isNotEmpty && combinedChartData.first.data.isNotEmpty
          ? combinedChartData.first.data.last.timestamp : null;
          
      if (latestData != null) {
        // 从已有的图表数据中提取属性
        for (var series in combinedChartData) {
          // 检查是否已存在该属性
          bool existsInProps = props.any((prop) => 
            prop.identifier == series.name || prop.name == series.name);
            
          if (!existsInProps) {
            props.add(PropertyDefinition(
              identifier: series.name,
              name: series.name,
              dataType: 'float', // 默认为浮点数
              accessMode: 1, // 只读
              desc: '',
            ));
          }
        }
      }
      
      // 手动添加可能缺失的波浪相关参数
      final waveParamIdentifiers = [
        'hmax_t', 'tmax_t', 'h3_t', 't3_t', 'h10_t', 't10_t', 'ha_t', 'ta_t', 
        'cropoints', 'dmean', 'dp', 'fp', 'hm0', 'tp', 'depth'
      ];
      
      for (var identifier in waveParamIdentifiers) {
        // 检查是否已存在该属性
        bool existsInProps = props.any((prop) => prop.identifier == identifier);
        
        if (!existsInProps) {
          props.add(PropertyDefinition(
            identifier: identifier,
            name: _getPropertyDisplayName(identifier),
            dataType: 'float', // 默认为浮点数
            accessMode: 1, // 只读
            desc: '',
          ));
        }
      }
      
      props.sort((a, b) => a.name.compareTo(b.name));
      properties.value = props;
      
      print('成功解析${props.length}个属性');
    } catch (e) {
      print('解析物模型JSON时出错: $e');
      properties.clear();
    }
  }
  
  // 添加一个辅助方法来获取属性的显示名称
  String _getPropertyDisplayName(String identifier) {
    // 为常见的波浪参数提供中文名称
    switch (identifier) {
      case 'hmax_t': return '最大波高';
      case 'tmax_t': return '最大波周期';
      case 'h3_t': return '1/3大波高';
      case 't3_t': return '1/3大波周期';
      case 'h10_t': return '1/10大波高';
      case 't10_t': return '1/10大波周期';
      case 'ha_t': return '平均波高';
      case 'ta_t': return '平均波周期';
      case 'cropoints': return '跨零点个数';
      case 'dmean': return '平均波向';
      case 'dp': return '主波向';
      case 'fp': return '峰值频率';
      case 'hm0': return '有效波高';
      case 'tp': return '峰值周期';
      case 'depth': return '水深';
      case 'W_temp': return '水温';
      case 'Bt_V': return '电池电压';
      case 'transmitTime': return '传输时间';
      case 'fname': return '设备名称';
      default: return identifier; // 对于其他标识符，使用原始标识符
    }
  }
  
  void _processHistoryData(List<dynamic> historyList, List<PropertyDefinition> props, Map<String, List<ChartDataPoint>> data) {
    try {
      // 先添加一个数据调试日志
      print('开始处理历史数据，数据条数: ${historyList.length}, 属性数量: ${props.length}');
      if (props.isNotEmpty) {
        print('首个属性: ${props[0].identifier}, ${props[0].name}');
      }
      
      // 创建一个临时映射，用于存储关键字到属性的映射
      Map<String, List<String>> propertyKeyMappings = {};
      for (var prop in props) {
        // 将属性标识符和名称转为小写，作为关键字
        String identifier = prop.identifier.toLowerCase();
        String name = prop.name.toLowerCase();
        
        // 将相似的波浪参数与标准名称建立映射关系
        List<String> possibleMatches = [identifier, name];
        
        // 添加常见的波浪参数别名
        if (identifier.contains('hmax') || name.contains('最大波高')) {
          possibleMatches.addAll(['hmax', 'hmax_t', 'h_max', '最大波高']);
        } else if (identifier.contains('tmax') || name.contains('最大波周期')) {
          possibleMatches.addAll(['tmax', 'tmax_t', 't_max', '最大波周期']);
        } else if (identifier.contains('h3') || name.contains('1/3大波高')) {
          possibleMatches.addAll(['h3', 'h3_t', 'h_3', 'h1/3', '1/3波高']);
        } else if (identifier.contains('t3') || name.contains('1/3大波周期')) {
          possibleMatches.addAll(['t3', 't3_t', 't_3', 't1/3', '1/3波周期']);
        } else if (identifier.contains('h10') || name.contains('1/10大波高')) {
          possibleMatches.addAll(['h10', 'h10_t', 'h_10', 'h1/10', '1/10波高']);
        } else if (identifier.contains('t10') || name.contains('1/10大波周期')) {
          possibleMatches.addAll(['t10', 't10_t', 't_10', 't1/10', '1/10波周期']);
        } else if (identifier.contains('ha') || name.contains('平均波高')) {
          possibleMatches.addAll(['ha', 'ha_t', 'h_a', 'havg', '平均波高']);
        } else if (identifier.contains('ta') || name.contains('平均波周期')) {
          possibleMatches.addAll(['ta', 'ta_t', 't_a', 'tavg', '平均波周期']);
        } else if (identifier.contains('cropoints') || name.contains('跨零点')) {
          possibleMatches.addAll(['cropoints', 'zeropoints', 'cro_points', '跨零点个数', '跨零点']);
        } else if (identifier.contains('dmean') || name.contains('平均波向')) {
          possibleMatches.addAll(['dmean', 'd_mean', 'dir_mean', '平均波向']);
        } else if (identifier.contains('dp') || name.contains('主波向')) {
          possibleMatches.addAll(['dp', 'd_p', 'dir_p', '主波向', '方向谱']);
        } else if (identifier.contains('fp') || name.contains('峰值频率')) {
          possibleMatches.addAll(['fp', 'f_p', 'freq_p', '峰值频率']);
        } else if (identifier.contains('hm0') || name.contains('有效波高')) {
          possibleMatches.addAll(['hm0', 'h_m0', 'h0', '有效波高']);
        } else if (identifier.contains('tp') || name.contains('峰值周期')) {
          possibleMatches.addAll(['tp', 't_p', 'period_p', '峰值周期']);
        } else if (identifier.contains('depth') || name.contains('水深')) {
          possibleMatches.addAll(['depth', 'water_depth', '水深']);
        } else if (identifier.contains('温度') || name.contains('温度')) {
          possibleMatches.addAll(['temp', 'temperature', 'w_temp', 'water_temp', '温度', '水温']);
        } else if (identifier.contains('电压') || name.contains('电压')) {
          possibleMatches.addAll(['voltage', 'v', 'bt_v', 'battery', '电压', '电池电压']);
        } else if (identifier.contains('fromcard') || name.contains('发送卡号')) {
          possibleMatches.addAll(['fromcard', 'from_card', 'sender', 'send_card', 'tocard', 'to_card', '发送卡号', '接收卡号']);
        }
        
        // 保存所有可能的匹配值
        String key = '${prop.name}${prop.unit != null ? "(${prop.unit})" : ""}';
        propertyKeyMappings[key] = possibleMatches;
      }
      
      // 用于调试的对象，记录每个属性的匹配情况
      Map<String, int> matchingCount = {};
      
      // 记录找到的所有字段名称
      Set<String> allFoundFields = {};
      
      for (var record in historyList) {
        if (record is! Map<String, dynamic>) {
          print('无效的历史记录格式: $record');
          continue;
        }
        
        // 检查timestamp字段
        if (!record.containsKey('timestamp') || record['timestamp'] == null) {
          print('记录缺少timestamp字段: $record');
          continue;
        }
        
        // 安全地转换timestamp
        DateTime? timestamp;
        try {
          final timestampValue = record['timestamp'];
          if (timestampValue is int) {
            timestamp = DateTime.fromMillisecondsSinceEpoch(timestampValue);
          } else if (timestampValue is String) {
            final parsedTimestamp = int.tryParse(timestampValue);
            if (parsedTimestamp != null) {
              timestamp = DateTime.fromMillisecondsSinceEpoch(parsedTimestamp);
            }
          }
        } catch (e) {
          print('解析timestamp失败: ${record['timestamp']}, 错误: $e');
        }
        
        if (timestamp == null) {
          print('无法解析timestamp: ${record['timestamp']}');
          continue;
        }
        
        // 检查properties字段
        dynamic properties;
        if (record.containsKey('properties') && record['properties'] != null) {
          properties = record['properties'];
        } else {
          // 尝试直接使用记录本身作为属性字典
          properties = record;
        }
        
        // 记录找到的所有字段名
        if (properties is Map) {
          properties.keys.forEach((key) {
            if (key != 'timestamp') {
              allFoundFields.add(key.toString());
            }
          });
        }
        
        if (!(properties is Map<String, dynamic>)) {
          print('properties字段不是有效的Map: $properties');
          continue;
        }

        // 为每个属性添加数据点
        for (var prop in props) {
          final key = '${prop.name}${prop.unit != null ? "(${prop.unit})" : ""}';
          
          if (!data.containsKey(key)) {
            print('未找到属性的数据列表: $key');
            continue;
          }
          
          // 尝试使用映射查找匹配的属性值
          dynamic value;
          String? matchedKey;
          
          if (propertyKeyMappings.containsKey(key)) {
            List<String> possibleMatches = propertyKeyMappings[key]!;
            
            // 尝试所有可能的匹配
            for (String match in possibleMatches) {
              for (String propKey in properties.keys) {
                if (propKey.toLowerCase() == match || 
                    propKey.toLowerCase().contains(match) || 
                    match.contains(propKey.toLowerCase())) {
                  value = properties[propKey];
                  matchedKey = propKey;
                  break;
                }
              }
              
              if (value != null) break;
            }
          }
          
          // 如果没有找到匹配，尝试直接使用identifier
          if (value == null && properties.containsKey(prop.identifier)) {
            value = properties[prop.identifier];
            matchedKey = prop.identifier;
          }
          
          // 记录匹配成功的次数
          if (value != null) {
            matchingCount[key] = (matchingCount[key] ?? 0) + 1;
          }
          
          if (value != null) {
            try {
              // 尝试将值转换为double
              double? doubleValue;
              
              if (value is num) {
                doubleValue = value.toDouble();
              } else if (value is String) {
                doubleValue = double.tryParse(value);
              }
              
              if (doubleValue != null && !doubleValue.isNaN && !doubleValue.isInfinite) {
                data[key]?.add(ChartDataPoint(
                  timestamp: timestamp,
                  value: doubleValue,
                ));
              }
            } catch (e) {
              print('解析属性 ${prop.identifier} 的值失败: $value, 错误: $e');
            }
          }
        }
      }
      
      // 打印匹配结果
      print('属性匹配结果:');
      matchingCount.forEach((key, count) {
        print('$key: 成功匹配 $count 条数据');
      });
      
      // 打印服务器上报的所有字段名
      print('服务器返回的所有字段:');
      print(allFoundFields.join(', '));
      
      // 检查哪些属性没有匹配到数据
      for (var prop in props) {
        final key = '${prop.name}${prop.unit != null ? "(${prop.unit})" : ""}';
        if (!matchingCount.containsKey(key) || matchingCount[key] == 0) {
          print('警告: 属性 $key 没有匹配到任何数据');
        }
      }
    } catch (e) {
      print('处理历史数据时发生错误: $e');
    }
  }
  
  void _generateCombinedChartData() {
    final List<ChartSeries> series = [];
    int colorIndex = 0;
    
    // 按数据点数量排序，优先显示数据量多的系列
    final sortedEntries = chartData.entries.toList()
      ..sort((a, b) => b.value.length.compareTo(a.value.length));
    
    // 显示所有数据系列，不再限制数量
    for (var entry in sortedEntries) {
      series.add(ChartSeries(
        name: entry.key,
        color: availableColors[colorIndex % availableColors.length],
        dataPoints: entry.value,
        isVisible: true, // 所有属性默认可见
      ));
      colorIndex++;
    }
    
    combinedChartData.value = series;
  }
  
  Future<void> refreshData() async {
    try {
      isLoading.value = true;
      errorMessage.value = null;
      
      // 验证设备ID是否有效
      if (deviceId <= 0) {
        errorMessage.value = '设备ID无效，请返回设备列表重新选择设备';
        isLoading.value = false;
        return;
      }
      
      isRefreshing.value = true;
      await loadData();
      
      // 添加调试信息
      analyzeHistoryDataStructure();
      
      isRefreshing.value = false;
    } catch (e) {
      print('刷新数据失败: $e');
      errorMessage.value = '刷新数据失败：$e';
    } finally {
      isLoading.value = false;
    }
  }
  
  void changeTimeRange(String range) {
    if (timeRange.value == range) return;
    
    timeRange.value = range;
    loadData();
  }
  
  void toggleCombinedChart() {
    showCombinedChart.value = !showCombinedChart.value;
  }
  
  void toggleSeriesVisibility(int index) {
    if (index >= 0 && index < combinedChartData.length) {
      final series = combinedChartData[index];
      series.isVisible.value = !series.isVisible.value;
    }
  }
  
  // 改进的loadData方法
  Future<void> loadData() async {
    if (isLoading.value) return;
    
    try {
      isLoading.value = true;
      errorMessage.value = null;
      
      // 设置超时保护
      const timeout = Duration(seconds: 10);
      
      // 同时执行设备序列号获取和物模型获取
      try {
        await Future.wait([
          _fetchDeviceSn().timeout(timeout, onTimeout: () {
            print('获取设备序列号超时');
            throw TimeoutException('获取设备序列号超时');
          }),
          _fetchThingModel().timeout(timeout, onTimeout: () {
            print('获取物模型超时');
            return;
          })
        ]).timeout(timeout, onTimeout: () {
          throw TimeoutException('初始化数据超时，请检查网络连接');
        });
        
        // 在获取到序列号和物模型后，获取历史数据
        await _fetchHistoryData().timeout(timeout, onTimeout: () {
          print('获取历史数据超时');
          return; // 允许显示空图表
        });
      } catch (e) {
        print('并行数据加载失败: $e');
        // 如果并行加载失败，尝试顺序加载核心数据
        if (deviceSn.isEmpty) {
          await _fetchDeviceSn().timeout(timeout, onTimeout: () {
            throw TimeoutException('获取设备序列号超时');
          });
        }
        
        if (properties.isEmpty) {
          try {
            await _fetchThingModel().timeout(timeout, onTimeout: () {
              return;
            });
          } catch (_) {
            print('获取物模型失败，未能创建默认物模型');
          }
        }
      }
    } on TimeoutException catch (e) {
      print('操作超时: $e');
      errorMessage.value = '网络请求超时，请检查网络连接后重试';
    } catch (e) {
      print('加载数据失败: $e');
      errorMessage.value = '加载数据失败：$e';
    } finally {
      isLoading.value = false;
    }
  }

  // 更新表格分页数据
  void _updateTablePagination() {
    // 收集所有唯一时间戳
    final allTimestampsSet = <DateTime>{};
    
    // 只考虑当前可见的系列
    final visibleSeries = combinedChartData
        .where((series) => series.isVisible.value)
        .toList();
        
    // 从可见系列中收集时间戳
    visibleSeries.forEach((series) {
      series.data.forEach((point) {
        allTimestampsSet.add(point.timestamp);
      });
    });

    // 对所有唯一时间戳进行排序（降序，最新的在前）
    final sortedTimestamps = allTimestampsSet.toList()..sort((a, b) => b.compareTo(a));
    
    // 更新当前页面显示的时间戳列表
    currentTimestamps.value = sortedTimestamps;
    
    // 使用服务器返回的总记录数，如果有的话
    if (serverTotalCount.value > 0) {
      totalTimestamps.value = serverTotalCount.value;
      print('使用服务器返回的总记录数: ${totalTimestamps.value}');
    } else {
      // 否则使用当前解析的时间戳数量
      totalTimestamps.value = sortedTimestamps.length;
      print('使用当前解析的时间戳数量: ${totalTimestamps.value}');
    }

    // 如果选择显示所有数据，则直接使用所有时间戳
    if (showAllData.value) {
      paginatedTimestamps.value = sortedTimestamps;
      print('显示所有数据: ${paginatedTimestamps.length}/${totalTimestamps.value}');
      return;
    }

    // 确保当前页不超过总页数
    final maxPage = totalTablePages;
    if (tableCurrentPage.value > maxPage && maxPage > 0) {
      tableCurrentPage.value = maxPage;
    }
    
    // 如果没有数据，确保回到第一页
    if (totalTimestamps.value == 0) {
      tableCurrentPage.value = 1;
      paginatedTimestamps.value = [];
      return;
    }

    // 计算当前页的起始和结束索引
    final startIndex = (tableCurrentPage.value - 1) * tablePageSize;
    int endIndex = startIndex + tablePageSize;

    // 确保结束索引不超过当前加载的数据范围
    if (endIndex > currentTimestamps.length) {
      endIndex = currentTimestamps.length;
    }
    
    // 获取当前页的时间戳列表
    if (startIndex < currentTimestamps.length) {
      paginatedTimestamps.value = currentTimestamps.sublist(startIndex, endIndex);
    } else {
      paginatedTimestamps.value = []; // 如果起始索引超出范围，则当前页为空
      if (currentTimestamps.isNotEmpty) {
        // 回到第一页
        tableCurrentPage.value = 1;
        // 重新获取第一页的数据
        final newEndIndex = tablePageSize;
        paginatedTimestamps.value = currentTimestamps.sublist(0, 
            newEndIndex > currentTimestamps.length ? currentTimestamps.length : newEndIndex);
      }
    }
    
    print('表格分页更新: 页 ${tableCurrentPage.value}/$totalTablePages, 时间戳数量: ${paginatedTimestamps.length}/${totalTimestamps.value}');
  }

  // 表格翻页方法
  void nextTablePage() {
    if (tableCurrentPage.value < totalTablePages) {
      tableCurrentPage.value++;
      _updateTablePagination();
    }
  }

  void previousTablePage() {
    if (tableCurrentPage.value > 1) {
      tableCurrentPage.value--;
      _updateTablePagination();
    }
  }

  // 新增：切换是否显示所有数据
  void toggleShowAllData() {
    showAllData.value = !showAllData.value;
    _updateTablePagination();
  }

  // 直接添加一个从历史数据中获取属性值的方法，以供表格使用
  dynamic getPropertyValueForTimestamp(String identifier, DateTime timestamp) {
    // 检查是否有历史数据缓存
    final cacheKey = '${deviceSn.value}_${timeRange.value}';
    if (!_historyDataCache.containsKey(cacheKey)) {
      print('历史数据缓存未找到');
      return null;
    }
    
    final historyData = _historyDataCache[cacheKey];
    if (historyData == null || !historyData.containsKey('list')) {
      print('历史数据缓存中没有list字段');
      return null;
    }
    
    final historyList = historyData['list'];
    if (historyList is! List || historyList.isEmpty) {
      print('历史数据list为空或非列表');
      return null;
    }
    
    // 尝试标准化属性标识符
    final normalizedIdentifier = identifier.toLowerCase().trim();
    
    // 创建可能的匹配名称列表
    List<String> possibleMatches = [normalizedIdentifier, identifier];
    
    // 特别处理一些特殊字段
    if (normalizedIdentifier == 'fname' || normalizedIdentifier == 'devicename' || normalizedIdentifier == '设备名称') {
      possibleMatches.addAll(['fname', 'Fname', 'deviceName', 'device_name', '设备名称', 'DeviceName', 'name']);
    } else if (normalizedIdentifier == 'transmittime' || normalizedIdentifier == '传输时间') {
      possibleMatches.addAll(['transmitTime', 'transmit_time', 'TransmitTime', '传输时间']);
    } else if (normalizedIdentifier == 'fromcard' || normalizedIdentifier == '接收卡号') {
      possibleMatches.addAll(['fromCard', 'FromCard', 'from_card', '接收卡号']);
    } else if (normalizedIdentifier == 'tocard' || normalizedIdentifier == '发送卡号') {
      possibleMatches.addAll(['toCard', 'ToCard', 'to_card', '发送卡号']);
    }
    
    // 添加常见的波浪参数别名
    else if (normalizedIdentifier.contains('hmax') || normalizedIdentifier.contains('最大波高')) {
      possibleMatches.addAll(['hmax', 'hmax_t', 'h_max', '最大波高']);
    } else if (normalizedIdentifier.contains('tmax') || normalizedIdentifier.contains('最大波周期')) {
      possibleMatches.addAll(['tmax', 'tmax_t', 't_max', '最大波周期']);
    } else if (normalizedIdentifier.contains('h3') || normalizedIdentifier.contains('1/3大波高')) {
      possibleMatches.addAll(['h3', 'h3_t', 'h_3', 'h1/3', '1/3波高']);
    } else if (normalizedIdentifier.contains('t3') || normalizedIdentifier.contains('1/3大波周期')) {
      possibleMatches.addAll(['t3', 't3_t', 't_3', 't1/3', '1/3波周期']);
    } else if (normalizedIdentifier.contains('h10') || normalizedIdentifier.contains('1/10大波高')) {
      possibleMatches.addAll(['h10', 'h10_t', 'h_10', 'h1/10', '1/10波高']);
    } else if (normalizedIdentifier.contains('t10') || normalizedIdentifier.contains('1/10大波周期')) {
      possibleMatches.addAll(['t10', 't10_t', 't_10', 't1/10', '1/10波周期']);
    } else if (normalizedIdentifier.contains('ha') || normalizedIdentifier.contains('平均波高')) {
      possibleMatches.addAll(['ha', 'ha_t', 'h_a', 'havg', '平均波高']);
    } else if (normalizedIdentifier.contains('ta') || normalizedIdentifier.contains('平均波周期')) {
      possibleMatches.addAll(['ta', 'ta_t', 't_a', 'tavg', '平均波周期']);
    } else if (normalizedIdentifier.contains('cropoints') || normalizedIdentifier.contains('跨零点')) {
      possibleMatches.addAll(['cropoints', 'zeropoints', 'cro_points', '跨零点个数', '跨零点', 'CroPoints']);
    } else if (normalizedIdentifier.contains('dmean') || normalizedIdentifier.contains('平均波向')) {
      possibleMatches.addAll(['dmean', 'd_mean', 'dir_mean', '平均波向', 'Dmean']);
    } else if (normalizedIdentifier.contains('dp') || normalizedIdentifier.contains('主波向')) {
      possibleMatches.addAll(['dp', 'd_p', 'dir_p', '主波向', '方向谱', 'Dp']);
    } else if (normalizedIdentifier.contains('fp') || normalizedIdentifier.contains('峰值频率')) {
      possibleMatches.addAll(['fp', 'f_p', 'freq_p', '峰值频率', 'Fp']);
    } else if (normalizedIdentifier.contains('hm0') || normalizedIdentifier.contains('有效波高')) {
      possibleMatches.addAll(['hm0', 'h_m0', 'h0', '有效波高', 'Hm0']);
    } else if (normalizedIdentifier.contains('tp') || normalizedIdentifier.contains('峰值周期')) {
      possibleMatches.addAll(['tp', 't_p', 'period_p', '峰值周期', 'Tp']);
    }
    
    // 在历史数据中查找与给定timestamp匹配的记录
    for (var record in historyList) {
      if (record is! Map<String, dynamic>) continue;
      
      // 尝试获取时间戳
      int? recordTimestamp;
      if (record.containsKey('timestamp')) {
        final ts = record['timestamp'];
        if (ts is int) {
          recordTimestamp = ts;
        } else if (ts is String) {
          recordTimestamp = int.tryParse(ts);
        }
      }
      
      if (recordTimestamp == null) continue;
      
      // 将记录时间戳转换为DateTime
      final recordDateTime = DateTime.fromMillisecondsSinceEpoch(recordTimestamp);
      
      // 比较时间戳，允许1秒误差
      if ((recordDateTime.difference(timestamp).inSeconds).abs() <= 1) {
        // 查找属性
        Map<String, dynamic>? properties;
        if (record.containsKey('properties') && record['properties'] is Map<String, dynamic>) {
          properties = record['properties'] as Map<String, dynamic>;
        } else {
          // 如果没有properties字段，尝试使用记录本身
          properties = record;
        }
        
        if (properties == null) continue;
        
        // 特别处理特殊的属性名称格式问题
        if (normalizedIdentifier == 'fname' || normalizedIdentifier == 'devicename' || normalizedIdentifier == '设备名称') {
          final value = properties['fname'] ?? properties['Fname'] ?? properties['deviceName'] ?? properties['设备名称'];
          if (value != null) return value;
        } else if (normalizedIdentifier == 'transmittime' || normalizedIdentifier == '传输时间') {
          final value = properties['transmitTime'] ?? properties['TransmitTime'] ?? properties['传输时间'];
          if (value != null) return value;
        }
        
        // 尝试查找匹配的属性
        for (String match in possibleMatches) {
          // 1. 精确匹配
          if (properties.containsKey(match)) {
            return properties[match];
          }
          
          // 2. 大小写不敏感匹配
          for (String key in properties.keys) {
            final keyLower = key.toLowerCase();
            if (keyLower == match.toLowerCase()) {
              return properties[key];
            }
          }
          
          // 3. 部分匹配
          for (String key in properties.keys) {
            final keyLower = key.toLowerCase();
            final matchLower = match.toLowerCase();
            if (keyLower.contains(matchLower) || matchLower.contains(keyLower)) {
              return properties[key];
            }
          }
        }
        
        // 如果所有匹配都失败，但我们找到了正确的时间戳，则直接检查原始标识符
        if (properties.containsKey(identifier)) {
          return properties[identifier];
        }
        
        // 临时调试
        if (normalizedIdentifier == 'fname' || normalizedIdentifier == 'devicename' || normalizedIdentifier == '设备名称') {
          print('未找到设备名称，可用属性: ${properties.keys.join(', ')}');
        } else if (normalizedIdentifier == 'transmittime' || normalizedIdentifier == '传输时间') {
          print('未找到传输时间，可用属性: ${properties.keys.join(', ')}');
        }
      }
    }
    
    // 如果没有找到，返回null
    return null;
  }
  
  // 分析加载的历史数据结构，打印到控制台
  void analyzeHistoryDataStructure() {
    final cacheKey = '${deviceSn.value}_${timeRange.value}';
    if (!_historyDataCache.containsKey(cacheKey)) {
      print('历史数据缓存未找到');
      return;
    }
    
    final historyData = _historyDataCache[cacheKey];
    if (historyData == null) {
      print('历史数据缓存为空');
      return;
    }
    
    print('===== 历史数据结构分析 =====');
    print('数据类型: ${historyData.runtimeType}');
    print('顶级字段: ${historyData.keys.join(', ')}');
    
    if (historyData.containsKey('list')) {
      final list = historyData['list'];
      print('list字段类型: ${list.runtimeType}');
      
      if (list is List && list.isNotEmpty) {
        print('记录数量: ${list.length}');
        
        // 分析第一条记录
        final firstRecord = list.first;
        print('第一条记录类型: ${firstRecord.runtimeType}');
        
        if (firstRecord is Map) {
          print('第一条记录字段: ${firstRecord.keys.join(', ')}');
          
          // 分析properties字段
          if (firstRecord.containsKey('properties')) {
            final props = firstRecord['properties'];
            print('properties字段类型: ${props.runtimeType}');
            
            if (props is Map) {
              print('属性字段: ${props.keys.join(', ')}');
              
              // 分析几个属性的数据类型
              props.forEach((key, value) {
                print('属性 $key 类型: ${value.runtimeType}, 值: $value');
              });
            }
          } else {
            print('记录不包含properties字段，直接使用顶级字段:');
            firstRecord.forEach((key, value) {
              if (key != 'timestamp') {
                print('字段 $key 类型: ${value.runtimeType}, 值: $value');
              }
            });
          }
        }
      }
    }
    
    print('==============================');
  }
} 